package com.block.common.util;



import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.crypto.symmetric.AES;
import com.block.common.security.util.AESUtil;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


/**
 * Created by Administrator on 2017/9/19.
 */
public class AESOperator {

    /*
    * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式，key需要为16位。
    */
    private static String ivParameter = "0392039203920300";
    private static AESOperator instance = null;

    private AESOperator() {

    }

    public static AESOperator getInstance() {
        if (instance == null) {
            instance = new AESOperator();
        }
        return instance;
    }

    public static String Encrypt(String encData , String secretKey, String vector) throws Exception {

        if(secretKey == null) {
            return null;
        }
        if(secretKey.length() != 16) {
            return null;
        }
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = secretKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8"));
        return Base64Encoder.encode(encrypted);// 此处使用BASE64做转码。
    }


    // 加密
    public static String encrypt(String sSrc,String sKey) throws UnsupportedEncodingException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException{
        try {
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			byte[] raw = sKey.getBytes();
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
			byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
			return AESUtil.parseByte2HexStr(encrypted);// 此处使用BASE64做转码。
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			throw e;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			throw e;
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			throw e;
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
			throw e;
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
			throw e;
		} catch (BadPaddingException e) {
			e.printStackTrace();
			throw e;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw e;
		}
    }

    // 解密
    public static String decrypt(String sSrc,String sKey) throws Exception{
        try {
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = Base64Decoder.decode(sSrc);// 先用16进制解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
           throw ex;
        }
    }

    public static String decrypt16(String sSrc,String sKey) throws Exception{
        try {
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = AESUtil.parseHexStr2Byte(sSrc);// 先用16进制解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            throw ex;
        }
    }

    public static String aesDecrypt(String sSrc,String sKey) throws Exception{
        try {
            AES aes = new AES("CBC", "PKCS7Padding",
                    // 密钥，可以自定义
                    sKey.getBytes(),
                    // iv加盐，按照实际需求添加
                    "0392039203920300".getBytes());
            String decryptStr = aes.decryptStr(sSrc);
            return decryptStr;
        } catch (Exception ex) {
            throw ex;
        }
    }

    public static String aesEncrypt(String sSrc,String sKey) throws Exception{
        try {
            AES aes = new AES("CBC", "PKCS7Padding",
                    // 密钥，可以自定义
                    sKey.getBytes(),
                    // iv加盐，按照实际需求添加
                    "0392039203920300".getBytes());
            String decryptStr = aes.encryptBase64(sSrc);
            return decryptStr;
        } catch (Exception ex) {
            throw ex;
        }
    }

    public static String encrypt16ByKey(String sSrc,String sKey) throws Exception{
        try {
            AES aes = new AES("CBC", "PKCS7Padding",
                    // 密钥，可以自定义
                    sKey.getBytes(),
                    // iv加盐，按照实际需求添加
                    "0392039203920300".getBytes());
            String decryptStr = aes.encryptBase64(sSrc);
            String result = Base64Encoder.encode(Base64Encoder.encode(decryptStr));// 先用16进制解密
            return result;
        } catch (Exception ex) {
            throw ex;
        }
    }

    public static String decrypt16ByKey(String sSrc,String sKey) throws Exception{
        try {
            AES aes = new AES("CBC", "PKCS7Padding",
                    // 密钥，可以自定义
                    sKey.getBytes(),
                    // iv加盐，按照实际需求添加
                    "0392039203920300".getBytes());
//            String decryptStr = aes.decryptStr(Base64Decoder.decode(AESUtil.parseHexStr2Byte(sSrc)));
            String decryptStr = aes.decryptStr(Base64Decoder.decode(Base64Decoder.decode(sSrc)));
            return decryptStr;
        } catch (Exception ex) {
            throw ex;
        }
    }

    public static String decrypt(String sSrc,String key,String ivs) throws Exception {
        try {
            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivs.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = Base64Decoder.decode(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
//		String key = "8764ecf1cddec4464fa4295f6d046132";
////		String encodeStr = encrypt("爱打架在建瓯为先从年纪哦", key);
////		String decodeStr = decrypt("1899008af3ca8ac43eb8e124101b50e987cdbd23337aea8aade50e464e004e70f3e903ac93f471f5b474697418b2bf7ddc36fe76368a98575431cecf712e902a", key);
//		String priKey="MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEA+1QRyKrej1F334c244mLDOaQsA4h+IoOV2JAijKkfMYC5KvZMyzhZrVPlgoqBnfYcCNK/vsNx7Wc+b41N8xIcQIDAQABAkEA9R+epLe6j8+mebXYG/43R2LM9VkjWtPTfvjN97vC4AkVWRn8Wn0dl6oUEngoRKGDhMdroD2rX6AVE9l6jfLyHQIhAP24/0HozMT2dKT/d7CiA7lOsmeLg1e9siwrUrkt9JXHAiEA/ZWSJMihHO+deAetq269T0QxdWWpNRANH0FhDsZCUAcCIFMerhELkTnde60qPC3TheDJVUzyuZ6e+KXbs4gS9BO1AiEAgvAodjXiez5+4OuWEV8tATEFGMlVhcC0Bd+MbkSRGSECIQDCh0n4Da5wCGsjzx55PjMtYrpL+JKCbNsq/zedklncHw==";
//		String values="5Zz3yzgGPwWvuVxiaw4bprmPQ4Gjr5SqASjPanajROi9ckfRg1nvMYvoz3XjONuK+wjsk/qW0nG3oEPqIbQF7A==";
//		String d= new String(RSACoderUtil.decryptByPrivateKey(Base64Decoder.decode(values),priKey));
////		System.out.println(encodeStr);
////		System.out.println(decodeStr);
//		System.out.println("d:"+d);
	}

    //加密
    public static String encrypt1(String data, String key, String ivString) {
        //偏移量
        byte[] iv = ivString.getBytes();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int length = dataBytes.length;
            //计算需填充长度
            if (length % blockSize != 0) {
                length = length + (blockSize - (length % blockSize));
            }
            byte[] plaintext = new byte[length];
            //填充
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            //设置偏移量参数
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encryped = cipher.doFinal(plaintext);

            return Base64.encodeBase64String(encryped);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
